﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace cuttingAndConcatenationOfFiles
{
    class Program
    {
        static int readTheFileInfo(string filePath)
        {
            int numberOfBytes = 0;
            FileInfo f3 = new FileInfo(filePath);
            using (FileStream readOnlyStream = f3.OpenRead())
            {
                numberOfBytes = (int)f3.Length;
            }
            return numberOfBytes;
        }
        static byte[] readFile(string donorFilePath, int[] numbersOfParts, int sequenceNumber, bool IsLastPart)
        {            
            // get FileStream
            using (FileStream fStream = File.Open(donorFilePath, FileMode.Open))
            {
               // Console.Write("\nСодержимое буфера: ");
                int border;
                fStream.Position = (sequenceNumber - 1) * numbersOfParts[0];

                if (IsLastPart == true)
                {
                    byte[] bufferLast = new byte[numbersOfParts[1]];
                    border = numbersOfParts[1];
                    for (int i = 0; i < border; i++)
                    {
                        bufferLast[i] = (byte)fStream.ReadByte();
                    //    Console.Write("{0} ", bufferLast[i]);                        
                    }
                    return bufferLast;
                }
                else
                {
                    byte[] buffer = new byte[numbersOfParts[0]];
                    border = numbersOfParts[0];
                    for (int i = 0; i < border; i++)
                    {
                        buffer[i] = (byte)fStream.ReadByte();
                   //     Console.Write("{0} ", buffer[i]);
                    }
                return buffer;
                }
            }
        }
        //---------------------------------------------------------------
        static void writeFile(string pathOfWritingFile, byte[] bufferForWriting, int[] numbersOfParts)
        {
            // to write a buffer into the file-piece 
            using (FileStream fStream1 = File.Open(pathOfWritingFile, FileMode.Create))
            {
                         fStream1.Write(bufferForWriting, 0, bufferForWriting.Length);
            }
            return;
        }
        //---------------------------------------------------------------
        static int[] calculateCountOfBytesOfEachInterval(int numberOfIntervals, int numberOfBytes)
        {
            int[] quantityOfBytesOfEachInterval = new int[2];
            quantityOfBytesOfEachInterval[0] = numberOfBytes/numberOfIntervals;
            quantityOfBytesOfEachInterval[1] = quantityOfBytesOfEachInterval[0] + (numberOfBytes % numberOfIntervals);
            return quantityOfBytesOfEachInterval;
        }
        //----------------------------------------------------------------
        static bool divideAndWriteOfEachFile(string donorFilePath, int numberOfIntervals, int[] numbersOfParts)
        {
                  bool result = false;
                  byte[] buffer = new byte[numbersOfParts[0]]; //буфер для всех частей, кроме последней
                  byte[] bufferLast = new byte[numbersOfParts[1]]; //буфер для последней части
                  for (int sequenceNumber = 1; sequenceNumber <= numberOfIntervals; sequenceNumber++)
                  {
                      string pathOfWritingFile = donorFilePath + sequenceNumber; // создание имени файла для записи куска
                      if(sequenceNumber == numberOfIntervals)
                      {
                          bool IsLastPart = true;
                          bufferLast = readFile(donorFilePath, numbersOfParts, sequenceNumber, IsLastPart); // заполнение буфера
                          writeFile(pathOfWritingFile, bufferLast, numbersOfParts); // буфером записать файл
                      }
                      else
                      {
                          bool IsLastPart = false;
                          buffer = readFile(donorFilePath, numbersOfParts, sequenceNumber, IsLastPart); // заполнение буфера
                          writeFile(pathOfWritingFile, buffer, numbersOfParts);
                      }
                  }
                  result = true;
                  return result;
        }
        static string concatenation(string donorFilePath, int numberOfIntervals)
        {
            char[] seps = { '.' };

            string[] parts = donorFilePath.Split(seps);
            string clonePath = parts[0] + "Clone." + parts[1];
            // open file in which should write bytes
            using (FileStream fStreamClone = File.Open(clonePath, FileMode.Create))
            {
            for (int sequenceNumber = 1; sequenceNumber <= numberOfIntervals; sequenceNumber++)
            {
                string nameOfFile = donorFilePath + sequenceNumber;
                using (FileStream fStream = File.Open(nameOfFile, FileMode.Open))
                {
                    int countOfBytesInBuffer = (int)fStream.Length;
                    fStream.Position = 0;
                    byte[] buffer = new byte[countOfBytesInBuffer];
                    for(int i = 0; i < countOfBytesInBuffer; i++)
                    {
                            buffer[i] = (byte)fStream.ReadByte();
                  //          Console.Write("{0} ", buffer[i]);
                    }
                    //write buffer in clonefile

                    fStreamClone.Write(buffer, 0, countOfBytesInBuffer);
                }
            }
        } // end of using for writing stream
            return clonePath;
        }   

        static void Main(string[] args)
        {
            string path = "C:\\Temp\\fileForReading.png";     //txt";
            int numberOfFiles = readTheFileInfo(path);
            // Console.WriteLine("{0} байт в файле {1}\n", numberOfFiles, path);

            // --------------------------------------------------------------

            int numberOfIntervals = 7;
            int[] intervals = new int[2];
            // The intervals array involves count of byte of each ordinary piece and in the last piece as well. 
            intervals = calculateCountOfBytesOfEachInterval(numberOfIntervals, numberOfFiles);
            Console.WriteLine("Was divided the original file:\n\t\t {3} \n1) on {0} the parts by {1} bytes each, \n2) except for the last part of {2} bytes ", numberOfIntervals - 1, intervals[0], intervals[1], path);
            bool IsDonorFileDevided = divideAndWriteOfEachFile(path, numberOfIntervals, intervals);
            string cloneOfFile = concatenation(path, numberOfIntervals);
            Console.WriteLine("\n\nClone file:\n\t\t {0} \nwas made for file:\n\t\t {1}", cloneOfFile, path);

            Console.ReadKey();
        }
    }
}
